import Vue from 'vue'
import axios from 'axios'
import { baseURL, contentType, debounce, messageName, requestTimeout, successCode } from '@/config'
import qs from 'qs'
import router from '@/router'
import { isArray } from '@/utils/validate'
import local from '@/utils/local'
import { EXTERNAL } from "@/constant"

const Base64 = require('js-base64').Base64

// const baseURL = process.env.NODE_ENV === 'production' ? '/apiconnector-web-admin' : process.env.VUE_APP_BASE_API
let loadingInstance

// 操作正常Code数组
const codeVerificationArray = isArray(successCode)
  ? [...successCode]
  : [...[successCode]]

const CODE_MESSAGE = {
  200: '服务器成功返回请求数据',
  201: '新建或修改数据成功',
  202: '一个请求已经进入后台排队(异步任务)',
  204: '删除数据成功',
  400: '发出信息有误',
  401: '用户没有权限(令牌、用户名、密码错误)',
  403: '用户得到授权，但是访问是被禁止的',
  404: '访问资源不存在',
  406: '请求格式不可得',
  410: '请求资源被永久删除，且不会被看到',
  500: '服务器发生错误',
  502: '网关错误',
  503: '服务不可用，服务器暂时过载或维护',
  504: '网关超时'
}

const handleData = ({ config, data = {}, status, statusText, headers }) => {
  if (config.baseURL === '/' && (config.url.indexOf('/auth') !== -1 || config.url.indexOf('/aba-base') !== -1)) {
    if (status === 200 || status === 201) {
      const status_code = headers['status_code']
      if (status_code && status_code !== '200') {
        const message = Base64.decode(headers['status_msg']) || '请稍后重试'
        return { code: status_code, message }
      }
    } else {
      const status_code = headers['status_code']
      if (status_code && status_code !== '200') {
        const message = Base64.decode(headers['status_msg']) || '请稍后重试'
        Object.assign(data, {
          code: status_code,
          message
        })
      }
    }
  }
  // return Promise.reject({code,message});
  if (loadingInstance) loadingInstance.close()
  // 因为第三方接口可能存在各种code定义，这里放开
  // 极个别情况，若将错误code设置为0时，防止识别成false影响判断
  // if (data[statusName] === 0) data[statusName] = '0'
  // 若data.code存在，覆盖默认code
  let code = status;
  if (config.url.indexOf('/proxytest') === -1) {
    // 不是接口测试返回的结果需要根据状态码进行判断
    code = data.code || status;
    // 若code属于操作正常code，则status修改为200
    if (codeVerificationArray.includes(code)) code = 200
  }
  switch (code) {
    case 200:
    case 'SUCCESS':
      // 业务层级错误处理，以下是假定restful有一套统一输出格式(指不管成功与否都有相应的数据格式)情况下进行处理
      // 例如响应内容：
      // 错误内容：{ status: 1, msg: '非法参数' }
      // 正确内容：{ status: 200, data: {  }, msg: '操作正常' }
      // 修改返回内容为 `data` 内容，对于绝大多数场景已经无须再关心业务状态码(code)和消息(msg)
      // return data.data ? data.data : data.msg
      // 或者依然保持完整的格式
      if (config.getHeaders) {
        return {
          data,
          headers,
          status
        }
      }
      return data
    case 401:
    case 'NotExistAccessToken':
      local.remove('token')
      local.remove('ms_username')
      local.remove('urlNamespace')
      Vue.prototype.$baseMessage('登录已过期，请重新登录', 'error', false, 'vab-hey-message-error')
      const loginUrl = EXTERNAL.yunshanUrl
      // 登录超时，跳转到云杉平台登录页面
      if (loginUrl) {
        setTimeout(() => {
          window.location.href = loginUrl.lastIndexOf('/') === -1 ? loginUrl + '/login' : loginUrl + 'login'
        }, 1000)
      } else {
        router.push({ path: '/login', replace: true })
      }
      return
    case 403:
      router.push({ path: '/403' })
      break
    case 500:
      if (config.getHeaders) {
        return {
          data,
          headers,
          status
        }
      }
  }
  // 异常处理
  // 若有自定义的异常处理，则调用，没有则统一处理
  // 若data.msg存在，覆盖默认提醒消息
  const internalMessage = buildMessage(code, data, statusText)
  const message = `${config.url} 后端接口 ${code} 异常：${internalMessage}`
  console.log(message)
  const { errorHandle } = config
  if (errorHandle && typeof errorHandle === 'function') {
    errorHandle(internalMessage)
  } else {
    Vue.prototype.$baseMessage(internalMessage, 'error', false, 'vab-hey-message-error')
  }
  return Promise.reject(message)
}

const buildMessage = (code, data, statusText) => {
  let message = CODE_MESSAGE[code];
  // 消息处理，首先判断data是否为空，不为空则从data中获取
  if (data && Object.prototype.toString.call(data) === '[object Object]') {
    if (data.hasOwnProperty(messageName)) {
      message = data[messageName]
    } else if (data.hasOwnProperty("msg")) {
      message = data['msg']
    }
  }
  if (!message) {
    message = statusText
  }
  return message
}

/**
 * @description axios初始化
 */
const instance = axios.create({
  baseURL,
  timeout: requestTimeout,
  headers: {
    'Content-Type': contentType
  }
})

/**
 * @description axios请求拦截器
 */
instance.interceptors.request.use(
  (config) => {
    // const token = store.getters['user/token']
    // 是否需要设置 token
    const isToken = (config.headers || {}).isToken === false
    const token = local.get('token') || {}
    if (token['token'] && !isToken) {
      config.headers['Authorization'] = 'Bearer ' + token['token'] // 让每个请求携带自定义token 请根据实际情况自行修改
    }
    if (process.env.NODE_ENV === 'development') {
      config.headers['user_id'] = 'BPMVQM09'
      config.headers['current_tenant'] = '47SEB09'
      config.headers['display_name'] = 'cmNfYWRtaW4x'
      config.headers['supper'] = 'true'
    }
    // 不规范写法 可根据setting.config.js tokenName配置随意自定义headers
    // if (token) config.headers[tokenName] = token

    // 规范写法 不可随意自定义
    // if (token) config.headers['Authorization'] = `Bearer ${token} `

    if (
      config.data &&
      config.headers['Content-Type'] ===
        'application/x-www-form-urlencoded;charset=UTF-8'
    ) { config.data = qs.stringify(config.data) }
    if (debounce.some((item) => config.url.includes(item))) { loadingInstance = Vue.prototype.$baseLoading() }
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

/**
 * @description axios响应拦截器
 */
instance.interceptors.response.use(
  (response) => handleData(response),
  (error) => {
    const { response } = error
    if (response === undefined) {
      Vue.prototype.$baseMessage(
        '未可知错误，大部分是由于后端不支持跨域CORS或无效配置引起',
        'error'
      )
      return Promise.reject('未可知错误')
    } else return handleData(response)
  }
)

export default instance
